解决CoordinatorLayout嵌套WebView,无法添加NestedScrollView,导致滑动冲突

您所在的位置:网站首页 python webview 解决CoordinatorLayout嵌套WebView,无法添加NestedScrollView,导致滑动冲突

解决CoordinatorLayout嵌套WebView,无法添加NestedScrollView,导致滑动冲突

#解决CoordinatorLayout嵌套WebView,无法添加NestedScrollView,导致滑动冲突| 来源: 网络整理| 查看: 265

最近在项目中使用到了CoordinatorLayout和AppBarLayout,主要是为了实现当向上滑动的时候顶部部分布局隐藏,但是对于下方布局是RecycleView时没有问题,但是我们下方使用的是TabLayout+ViewPager,并且Fragment中使用的是WebView. 在正常使用的情况下,我们会在WebView外层嵌套NestedScrollView来配合CoordinatorLayout使用。但是用一种特殊情况:H5页面中如果有悬浮控件,悬浮控件会丢失位置。 其根本原因是:WebView在谷歌的材料设计库中并不支持CoordinatorLayout滚动技术,也就是说CoordinatorLayout不支持和WebView协同使用。 解决办法: 1、在WebView外层套上NestedScrollView

这样处理虽然简单,但是可能导致WebView中的某些JS方法无法使用。

2、重写WebView实现NestedScrollingChild

/** * NestedScrollWebView to */ public class NestedScrollWebView extends WebView implements NestedScrollingChild { public static final String TAG = NestedScrollWebView.class.getSimpleName(); private int mLastMotionY; private final int[] mScrollOffset = new int[2]; private final int[] mScrollConsumed = new int[2]; private int mNestedYOffset; private NestedScrollingChildHelper mChildHelper; public NestedScrollWebView(Context context) { super(context); init(); } public NestedScrollWebView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public NestedScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mChildHelper = new NestedScrollingChildHelper(this); setNestedScrollingEnabled(true); } @Override public boolean onTouchEvent(MotionEvent event) { boolean result = false; MotionEvent trackedEvent = MotionEvent.obtain(event); final int action = MotionEventCompat.getActionMasked(event); if (action == MotionEvent.ACTION_DOWN) { mNestedYOffset = 0; } int y = (int) event.getY(); event.offsetLocation(0, mNestedYOffset); switch (action) { case MotionEvent.ACTION_DOWN: mLastMotionY = y; int nestedScrollAxis = ViewCompat.SCROLL_AXIS_VERTICAL; nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL; //按位或运算 // startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); startNestedScroll(nestedScrollAxis); result = super.onTouchEvent(event); break; case MotionEvent.ACTION_MOVE: int deltaY = mLastMotionY - y; if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { deltaY -= mScrollConsumed[1]; trackedEvent.offsetLocation(0, mScrollOffset[1]); mNestedYOffset += mScrollOffset[1]; } int oldY = getScrollY(); mLastMotionY = y - mScrollOffset[1]; int newScrollY = Math.max(0, oldY + deltaY); deltaY -= newScrollY - oldY; if (dispatchNestedScroll(0, newScrollY - deltaY, 0, deltaY, mScrollOffset)) { mLastMotionY -= mScrollOffset[1]; trackedEvent.offsetLocation(0, mScrollOffset[1]); mNestedYOffset += mScrollOffset[1]; } if (mScrollConsumed[1] == 0 && mScrollOffset[1] == 0) { trackedEvent.recycle(); result = super.onTouchEvent(trackedEvent); } break; case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: stopNestedScroll(); result = super.onTouchEvent(event); break; } return result; } // NestedScrollingChild @Override public void setNestedScrollingEnabled(boolean enabled) {//设置嵌套滑动是否可用 mChildHelper.setNestedScrollingEnabled(enabled); } @Override public boolean isNestedScrollingEnabled() {//嵌套滑动是否可用 return mChildHelper.isNestedScrollingEnabled(); } /** * 开始嵌套滑动, * * @param axes 表示方向 有一下两种值 * ViewCompat.SCROLL_AXIS_HORIZONTAL 横向滑动 * ViewCompat.SCROLL_AXIS_VERTICAL 纵向滑动 */ @Override public boolean startNestedScroll(int axes) { return mChildHelper.startNestedScroll(axes); } @Override public void stopNestedScroll() {//停止嵌套滑动 mChildHelper.stopNestedScroll(); } @Override public boolean hasNestedScrollingParent() {//是否有父View 支持 嵌套滑动, 会一层层的网上寻找父View return mChildHelper.hasNestedScrollingParent(); } /** * 在处理滑动之后 调用 * * @param dxConsumed x轴上 被消费的距离 * @param dyConsumed y轴上 被消费的距离 * @param dxUnconsumed x轴上 未被消费的距离 * @param dyUnconsumed y轴上 未被消费的距离 * @param offsetInWindow view 的移动距离 * @return */ @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); } /** * 一般在滑动之前调用, 在ontouch 中计算出滑动距离, 然后调用该方法, 就给支持的嵌套的父View 处理滑动事件 * * @param dx x 轴上滑动的距离, 相对于上一次事件, 不是相对于 down事件的 那个距离 * @param dy y 轴上滑动的距离 * @param consumed 一个数组, 可以传 一个空的 数组, 表示 x 方向 或 y 方向的事件 是否有被消费 * @param offsetInWindow 支持嵌套滑动到额父View 消费 滑动事件后 导致 本 View 的移动距离 * @return 支持的嵌套的父View 是否处理了 滑动事件 */ @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); } /** * @param velocityX x 轴上的滑动速度 * @param velocityY y 轴上的滑动速度 * @param consumed 是否被消费 * @return */ @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); } /** * @param velocityX x 轴上的滑动速度 * @param velocityY y 轴上的滑动速度 * @return */ @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); } }

参考链接: webview-in-coordinator-layout NestedScrollWebView



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3